#include "RunQUT.h"

#include <QtDebug>
#include <QCoreApplication>
#include <QLibrary>
#include <QTimer>

#include <quick/QutRunner.h>
#include <base/BaseLog.h>

RunQUT::RunQUT(QObject * parent)
    : QObject(parent)
    , stdout_flags(Summary | Expect)
    , mStdout(stdout, QIODevice::WriteOnly)
    , mLastEventIndex(-1)
{
}

void RunQUT::showEvents(void)
{
#if 1
    int eventCount = QutRunner().eventCount();
    int index = mLastEventIndex + 1;
    qDebug("showEvents() eventCount=%i index=%i", eventCount, index);
    while (index < eventCount)
    {
        QutCase event = QutRunner().eventAt(index);
        processTestCase(event);
        mLastEventIndex = index++;
    }
#endif
}

void RunQUT::initialize(void)
{
#if 0
    Q_ASSERT(connect(QutRunner::p(), SIGNAL(eventAdded(QutCase)),
            this, SLOT(processEvent(QutCase))));
#else
    Q_ASSERT(connect(QutRunner::p(), &QutRunner::addTestCase,
                     this, &RunQUT::processTestCase));
#endif
    QTimer::singleShot(100, this, SLOT(processCommands()));
    emit initialized();
//    QObject::dumpObjectInfo();
}

void RunQUT::processCommands(void)
{
    libNames_qsl << "eirBase" << "eirType";
    QTimer::singleShot(100, this, SLOT(start()));
    emit commandsProcessed();
    showEvents();
}

void RunQUT::start(void)
{
    if (libNames_qsl.isEmpty())
    {
        QTimer::singleShot(100, this, SLOT(leave()));
        emit nothing();
    }
    else
    {
        QTimer::singleShot(100, this, SLOT(nextLibrary()));
        emit started();
    }
    showEvents();
}

void RunQUT::nextLibrary(void)
{
//    QObject::dumpObjectInfo();
    if (libNames_qsl.isEmpty())
    {
        QTimer::singleShot(100, this, SLOT(finish()));
        emit doneTesting();
        return;
    }



    QString libName(libNames_qsl.takeFirst());
    QLibrary lib(libName, this);
    QString error = QutRunner().Test(&lib);

    libName_error_spl << StringPair(libName, error);
    if ( ! error.isEmpty()) mStdout << error << libName << endl;
    QTimer::singleShot(100, this, SLOT(libraryFinish()));
    mMax_level = QutRunner().maxLevel();
    emit libraryTested(mMax_level);
    showEvents();
}

void RunQUT::processTestCase(QutCase event)
{
    //BTRACE("RunQUT::processEvent(%1)", event.toString());
    //qDebug(qPrintable(event.toString()));
    mStdout << event.toString() << endl;
}

void RunQUT::libraryFinish(void)
{
    if (mMax_level < QutCase::Quit)
    {
        nextLibrary();
    }
    else
    {
        QTimer::singleShot(100, this, SLOT(finish()));
        emit doneTesting();
    }
    showEvents();
}

void RunQUT::finish(void)
{
    QutRunner().finish();
    _summary = QutRunner().summary();
    QTimer::singleShot(100, this, SLOT(results()));
    emit finished();
    showEvents();
}

void RunQUT::results(void)
{
    if (results_url.isValid())
    {
        mStdout << "Writing results to" << results_url.toString() << endl;
    }
    QTimer::singleShot(100, this, SLOT(report()));
    emit resultsFinished();
}

void RunQUT::report(void)
{
    if (report_url.isValid())
    {
        mStdout << "Writing report to" << report_url.toString() << endl;
    }
    QTimer::singleShot(100, this, SLOT(leave()));
    emit reportFinished();
}

void RunQUT::leave(void)
{
    showEvents();
    QTimer::singleShot(10, qApp, SLOT(quit()));
}
